package com.ycl.javacore.javassist;

import javassist.*;
import org.junit.Test;

import java.lang.reflect.Constructor;

public class JavassistDemo {

    private static BookApi createJavassistBytecodeDynamicProxy() throws Exception {
        ClassPool mPool = new ClassPool(true);
        CtClass mCtc = mPool.makeClass(BookApi.class.getName() + "JavaassistProxy");
        mCtc.addInterface(mPool.get(BookApi.class.getName()));
        mCtc.addConstructor(CtNewConstructor.defaultConstructor(mCtc));
        mCtc.addMethod(CtNewMethod.make(
                "public void sell() { System.out.println(\"111\") ; }", mCtc));
        Class<?> pc = mCtc.toClass();
        BookApi bytecodeProxy = (BookApi) pc.newInstance();
        return bytecodeProxy;
    }

    @Test
    public void test() throws Exception {
        /*
        // 1、创建ClassPool：CtClass对象的容器
        ClassPool pool = ClassPool.getDefault();

        // 2、通过ClassPool生成一个public新类Hello.java
        CtClass ctClass = pool.makeClass("com.gude.Hello");
        //ctClass.setSuperclass(); 父类设置
        //ctClass.setInterfaces(); 接口设置

        // 3、添加属性
        CtField nameField = new CtField(pool.getCtClass("java.lang.String"),
                "name", ctClass);
        //设为私有
        nameField.setModifiers(Modifier.PRIVATE);
        ctClass.addField(nameField);
        //4、添加get set
        ctClass.addMethod(CtNewMethod.getter("getName", nameField));
        ctClass.addMethod(CtNewMethod.setter("setName", nameField));

        //5、添加自定义方法
        CtMethod ctMethod = new CtMethod(CtClass.voidType, "customMethod",
                new CtClass[]{}, ctClass);
        ctMethod.setModifiers(Modifier.PUBLIC);
        ctMethod.setBody("System.out.println(\"custome method\");");
        ctClass.addMethod(ctMethod);

        //6、添加Hello(String name)有参构造方法
        CtConstructor ctConstructor = new CtConstructor(new CtClass[]{pool.getCtClass("java.lang.String")}, ctClass);
        ctConstructor.setBody("{this.name=name;}");
        ctClass.addConstructor(ctConstructor);

        //无参构造
        CtConstructor cons = new CtConstructor(null, ctClass);
        cons.setBody("{}");
        ctClass.addConstructor(cons);

        //7、生成一个class
        Class<?> clazz = ctClass.toClass();

        //测试
        Object o = clazz.newInstance();
        clazz.getDeclaredMethod("customMethod").invoke(o);

        Constructor constructor = clazz.getConstructor(String.class);
        Object o1 = constructor.newInstance("ycl");
        clazz.getDeclaredMethod("getName").invoke(o1);
        System.out.println(o1.toString());
*/

        BookApi bookApi = createJavassistBytecodeDynamicProxy();
        bookApi.sell();

    }
}